home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-12-11 | 8.2 KB | 332 lines | [TEXT/PJMM] |
- { This file is a modified version of the file noCommentsProcs.p that illustrates }
- { writing a fairly simple application with MacStarter_pascal. It also illustrates }
- { some other useful stuff, which is commented below. }
-
- { This file uses a different resource file from the generic.π project; the file menu }
- { contains only a Quit command. }
-
- unit applicationProcs;
-
- interface
-
- uses
- xWindow, xControlDecoration, xTextWindow, TextReader;
- { the TextReader unit difines a class that provides easy accesss to }
- { the text in a TextWindow. }
-
-
- const
-
- maxSleepTime = 5;
- ApplicationShortName = 'Simple Stats';
- ApplicationLongName = 'Simple Stats';
- AuthorName = 'David Eck';
- AuthorAddress1 = 'Hobart and William Smith Colleges';
- AuthorAddress2 = 'Geneva, NY 14456';
- AuthorAddress3 = '(Email Address: eck@hws.BITNET)';
- CommentLine = 'Displays basic statistics for a list of numbers entered by user.';
-
-
-
- var
- editMenu: MenuHandle;
- fileMenu: MenuHandle;
-
-
- procedure InitializeApplication;
- procedure CleanUpApplication;
- procedure DoEditMenu (itemNum: integer);
- procedure DoFileMenu (itemNum: integer;
- var done: boolean);
- procedure DoOtherMenu (menuNum, itemNum: integer);
- procedure UpdateMenus;
- procedure ApplicationIdle;
-
-
- implementation
-
-
- type
-
- myButton = object(xButton)
- procedure HandleClick;
- override;
- end;
-
- myWin = object(xTextWindow)
- { A window where the user can type a list of numbers, then click a button to see the sum, }
- { average and standard deviation of the numbers entered.}
-
- reader: TextReader; { used to access the numbers typed by the user }
- bttn: myButton;
- sum, average, deviation: extended;
-
- procedure setDefaults;
- override;
- procedure openInRect (title: string;
- left, top, right, bottom: integer);
- override;
- procedure doRedraw (badRect: Rect);
- override;
- procedure doKey (ch: char;
- modifiers: longint);
- override;
- procedure doClose;
- override;
- procedure doStats;
- end;
-
-
-
-
- procedure myButton.HandleClick;
- { when the user clicks on the button, a message is sent to the window to calculate }
- { the statistics. }
- begin
- myWin(itsWindow).doStats
- end;
-
- procedure myWin.setDefaults;
- begin
- inherited setDefaults;
- minSize.h := 301; { set min and max sizes for "growing" window }
- maxSize.h := 301; { note that window has a fixed horizontal size }
- minSize.v := 150;
- features := features - [hasZoom]; { I have to remove the zoom box because zooming }
- { would not respect the fixed horizontal size. }
- topTextOffset := 50; { leave room for stuff at the top of the window. }
- vScrollTopOffset := 51;
- end;
-
- procedure myWin.openInRect (title: string;
- left, top, right, bottom: integer);
- begin
-
- right := left + 300; { make sure the opening size is the correct fixed horizontal size }
- inherited openInRect(title, left, top, right, bottom);
-
- new(bttn); { install button that will calculate statistics }
- bttn.setUp(self, 'Stats', 10, 15, 70, 20);
-
- new(reader); { create a text reader and set it up to read from this window. }
- reader.SetUpFromTextWindow(self);
-
- sum := badReal; { "badReal" is defined in unit TextReader; used here to indicate "no value" }
- average := badReal;
- deviation := badReal;
-
- end;
-
-
- {$PUSH}
- {$R-}
-
- procedure RealToString (x: extended;
- var s: string);
- { useful utility for getting a reasonable up-to-12-character representation of a real number; }
- { doesn't seem to be foolproof, though }
- var
- n, i: integer;
- begin
- if abs(x) <= 1 / badReal then
- s := '0'
- else if abs(x) >= badReal then
- s := '?'
- else if (abs(x) >= 5e8) or (abs(x) < 5e-8) then begin { exponential form }
- n := 15;
- repeat { this is needed since the stupid computer alllows 4 spaces for the exponent even if it is one two or three digits }
- s := StringOf(x : n);
- n := n - 1;
- i := length(s);
- while (i > 0) & (s[i] = ' ') do
- i := i - 1;
- s[0] := chr(i);
- until (length(s) <= 12) | (n = 11)
- end
- else begin
- s := StringOf(x : 1 : 10);
- i := length(s);
- while (i > 0) & (s[i] = '0') do { strip off trailing zeros }
- i := i - 1;
- if (i > 0) & (s[i] = '.') then { strip off terminating decimal point }
- i := i - 1;
- if i > 12 then { maximum length allowed for output is 12}
- s[0] := chr(12)
- else
- s[0] := chr(i);
- end
- end;
-
- {$POP}
-
-
-
- procedure myWin.doRedraw (badRect: Rect);
- var
- str: string;
- begin
-
- inherited doRedraw(badRect); { redraws text section of window; also redraws the button }
-
- moveTo(0, 50); { draw line separating text from button & stats }
- LineTo(theWindow^.portRect.right, 50);
-
- moveTo(100, 12); { write out the statistics }
- RealToString(sum, str);
- DrawString(Concat('Sum = ', str));
-
- moveTo(100, 29);
- RealToString(average, str);
- DrawString(Concat('Average = ', str));
-
- moveTo(100, 46);
- RealToString(deviation, str);
- DrawString(Concat('Deviation = ', str));
-
- end;
-
-
- procedure myWin.doKey (ch: char;
- modifiers: longint);
- { The doKey procedure for this window class is modified so that only line feeds and }
- { characters that can appear in real numbers are allowed. Furthermore, any }
- { "whitespace" character is converted into a line feed. Other characters make }
- { the computer beep. }
- begin
- if (ch = tab) | (ch = space) | (ch = ',') | (ch = chr(3)) then
- ch := endOfLine; { endOfLine is defined in UNIT TextReder. }
- if ch in [endOfLine, '0'..'9', '.', 'e', 'E', '+', '-', chr(8), chr($1c)..chr($1f)] then
- inherited doKey(ch, modifiers)
- else
- Sysbeep(1);
- end;
-
- procedure myWin.doClose;
- { for this simple program, it seemed best to quit when the user closes the }
- { unique window used by the program. }
- begin
- halt
- end;
-
- procedure myWin.doStats;
- { this is called when the user clicks on the button. It uses the TextReader, reader, }
- { to get the numbers that the user has typed in, and calculates the statistics for }
- { those numbers. }
- var
- ct: integer;
- total, sqTotal: extended;
- x: extended;
- R: Rect;
- begin
- ct := 0;
- reader.reset; { start reading from beginning of text in the window }
- reader.skipWhiteSpace;
-
- sum := badReal;
- average := badReal;
- deviation := badReal;
- total := 0;
- sqTotal := 0;
-
- SetPort(theWindow); { arrange for statistics listed at top of window to be re-written }
- R := theWindow^.portRect;
- R.bottom := 50;
- R.left := 100;
- InvalRect(R);
-
- while reader.moreChars do begin { get next number and add to totals }
- ct := ct + 1;
- reader.ReadReal(x);
- if reader.numError then begin
- TellUser('Illegal number found in data.');
- SetSelectionRange(reader.ErrorPosition, reader.ErrorPosition);
- ScrollToSelection;
- EXIT(doStats);
- end;
- if not (reader.next in [endOfData, endOfLine]) then begin
- TellUser('Illegal number found in data.');
- SetSelectionRange(reader.where, reader.where);
- ScrollToSelection;
- EXIT(doStats);
- end;
- total := total + x;
- sqTotal := sqTotal + sqr(x);
- reader.skipWhiteSpace;
- end;
-
- if ct = 0 then begin
- TellUser('You haven''t entered any data.');
- end
- else begin { compute statistics }
- sum := total;
- average := sum / ct;
- deviation := sqrt((sqTotal - sqr(total) / ct) / ct);
- end;
-
- end;
-
-
-
-
- procedure OpenAWindow;
- var
- Win: myWin;
- begin
- new(Win);
- Win.open('Basic Statistics');
- end;
-
- procedure InitializeApplication;
- begin
- OpenAWindow;
- end;
-
- procedure CleanUpApplication;
- begin
- end;
-
- procedure UpdateMenus;
- var
- i: integer;
- win: WindowPtr;
- begin
- win := FrontWindow; { this is the currently active window, or nil if there is none }
- if win = nil then
- DisableItem(fileMenu, 2)
- else
- EnableItem(fileMenu, 2);
- end;
-
-
- procedure CloseFrontWindow;
- var
- X: xWindow;
- begin
- if FrontWindow <> nil then
- if window2xWindow(FrontWindow, X) then
- X.doClose
- end;
-
- procedure DoFileMenu (itemNum: integer;
- var done: boolean);
- begin
- done := true; { only command in file menu is Quit! }
- end;
-
- procedure DoEditMenu (itemNum: integer);
- begin
- end;
-
- procedure DoOtherMenu (menuNum, itemNum: integer);
- begin
- end;
-
- procedure ApplicationIdle;
- var
- X: xWindow;
- begin
- if (window2xWindow(FrontWindow, X)) then
- X.idle;
- end;
-
- end.